#ifndef DRIVER_TTY_H
#define DRIVER_TTY_H

#include <os/driver.h>
#include <os/debug.h>
#include <os/memcache.h>
#include <os/spinlock.h>
#include <os/mutexlock.h>
#include <os/fifoio.h>
#include <sys/ioctl.h>

#define DRIVER_NAME "tty-driver"
#define DRIVER_NAME_LEN 32

#define DEVICE_NAME "tty"

#define KEYBOARD_DEVICE_NAME "keyboard"
#define CONSOLE_DEVICE_NAME "con"

// tty flags
#define TTY_FLAGS_ECHO 0x01
#define TTY_FLAGS_NOWAIT 0x02

// tty device number
#define TTY_DEVICE_NUM 8

// tty raw device
#define TTY_DEVICE_RAW 7

#define DEVICE_FIFO_BUFF_LEN 64

typedef struct _device_extension device_extension_t;

// device public
typedef struct _device_public
{
    device_handle_t current_device; // current device
    int detach_keyboard;            // detach keyboard
    device_extension_t *extension[TTY_DEVICE_NUM];
    int count;
} device_public_t;

// device extension
typedef struct _device_extension
{
    device_object_t *device_object;
    pid_t process_group_id;
    int device_id;
    device_handle_t console;
    device_handle_t keyboard;
    device_public_t *public;
    uint32_t modify_ctl;
    uint32_t modify_alt;

    fifo_io_t fifoio;
    uint32_t flags;
} device_extension_t;

static int inline TTYSetCurrent(device_extension_t *extension, int visitor)
{
    if (visitor < 0 || visitor >= TTY_DEVICE_NUM)
        return -1;
    extension->public->current_device = visitor;
    return 0;
}

// keyboard code map
static uint8_t _keycode_map_table[] = {
    KEY_KP_PERIOD,
    KEY_PERIOD, // .
    KEY_KP_MULTIPLY,
    KEY_ASTERISK, // *
    KEY_KP_PLUS,
    KEY_PLUS, // +
    KEY_KP_MINUS,
    KEY_MINUS, // -
    KEY_KP_DIVIDE,
    KEY_SLASH, // /
    KEY_KP0,
    KEY_0, // 0
    KEY_KP1,
    KEY_1, // 1
    KEY_KP2,
    KEY_2, // 2
    KEY_KP3,
    KEY_3, // 3
    KEY_KP4,
    KEY_4, // 4
    KEY_KP5,
    KEY_5, // 5
    KEY_KP6,
    KEY_6, // 6
    KEY_KP7,
    KEY_7, // 7
    KEY_KP8,
    KEY_8, // 8
    KEY_KP9,
    KEY_9, // 9
    0xff,
    KEY_UNKNOWN,
};

#endif